/*=============================================================================
Copyright (c) 2005 AUTOMATED LOGIC CORPORATION

This file is part of DominoTomcatSSOIntegration.
http://www.automatedlogic.com/domblog.nsf/dx/DominoTomcatSSOIntegration

DominoTomcatSSOIntegration is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

DominoTomcatSSOIntegration is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
http://www.gnu.org/licenses/gpl.html
=============================================================================*/

package com.automatedlogic.domino.sso;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;


/**
 * This filter is defined in the Apache Tomcat application's web.xml file, and will intercept requests
 * for web pages in Apache Tomcat.
 * <p/>
 * If the web user has already authenticated with the Domino server, there will be an
 * existing "DominoUserProfile" object stored in the user's session.  If this object does not exist,
 * then the user will be redirected to a Domino login page.  When authenticated successfully,
 * the user will be redirected back to the Apache Tomcat page they were attempting to open.
 * <p/>
 * The user's session should then have the "DominoUserProfile",
 * and is therefore "authenticated" for using the Apache Tomcat web server.
 *
 * @author Brian Green, Automated Logic Corporation, domino@automatedlogic.com
 * @version 2.4.3, Feb 25 2005
 * @see <a href="http://www.automatedlogic.com/domblog.nsf/dx/DominoTomcatSSOIntegration">Automated Logic Corporation</a>
 * @since JDK1.4.2_06
 */
public class DominoLoginFilter implements Filter {

    //Do not create other variables here besides FilterConfig.  This will keep the filter "thread safe".
    private FilterConfig config = null;

    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }

    public void destroy() {
        config = null;
    }


    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest http = (HttpServletRequest) servletRequest;
        HttpSession session = http.getSession();

        //Look for an existing DominoUserProfile that has already been stored in the user's session.
        DominoUserProfile dominoUserProfile;
        dominoUserProfile = (DominoUserProfile) session.getAttribute("DominoUserProfile");

        //If a user meets the requirements, allow the user to continue.
        if (continueFilter(http, dominoUserProfile)) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }




        //Login needed to continue.  The user requires authentication with the Domino server.
        boolean storeInSession = false;

        //Get the debug value.  Optional.  This is defined in web.xml.
        String debug = config.getInitParameter(DominoLoginFilterConstants.DOMINO_TOMCAT_LOGIN_DEBUG) == null ? "" : config.getInitParameter(DominoLoginFilterConstants.DOMINO_TOMCAT_LOGIN_DEBUG);

        //Get the location of the Domino server.  Required.  This is defined in web.xml.
        String dominoServer = config.getInitParameter(DominoLoginFilterConstants.DOMINO_DIIOP_CONNECTION) == null ? "" : config.getInitParameter(DominoLoginFilterConstants.DOMINO_DIIOP_CONNECTION);
        if (dominoServer.equals("")) {
            logMessage(debug, DominoLoginFilterConstants.MSG_DOMINO_DIIOP_CONNECTION_NOT_DEFINED);
            servletResponse.setContentType("text/html");
            servletResponse.getWriter().println(DominoLoginFilterConstants.MSG_DOMINO_DIIOP_CONNECTION_NOT_DEFINED);
            return;
        }

        //Get the location of the login application.  Required.  This is defined in web.xml.
        String loginURL = config.getInitParameter(DominoLoginFilterConstants.DOMINO_TOMCAT_LOGIN_CONTEXT) == null ? "" : config.getInitParameter(DominoLoginFilterConstants.DOMINO_TOMCAT_LOGIN_CONTEXT);
        if (loginURL.equals("")) {
            logMessage(debug, DominoLoginFilterConstants.MSG_TOMCAT_LOGIN_CONTEXT_NOT_DEFINED);
            servletResponse.setContentType("text/html");
            servletResponse.getWriter().println(DominoLoginFilterConstants.MSG_TOMCAT_LOGIN_CONTEXT_NOT_DEFINED);
            return;
        }

        //Does the user's session contain the DominoUserProfile object?
        if (dominoUserProfile == null) {
            //Try to create the DominoUserProfile.  This will look at the LtpaToken cookie stored in the web browser.
            //If the cookie exists, then the DominoUserProfile object will be created successfuly and then stored in the user's session.
            logMessage(debug, "You don't have an existing DominoUserProfile in your session!   If you have an existing LtpaToken cookie, you may continue...");
            dominoUserProfile = new DominoUserProfile();
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            //eqe
            String uname=(String) request.getSession().getAttribute("uname");
            String pword= (String) request.getSession().getAttribute("pword");
            String redirto = (String) request.getSession().getAttribute("redirto");
            //eqe
            dominoUserProfile.setPassword(pword);
            dominoUserProfile.setDominoUrl(redirto);    		
            //eqe
            dominoUserProfile.refresh(http, dominoServer);
            storeInSession = true;
        }

        //Does the user's session contain a dominoUserProfile object, and is it valid?
        if (!dominoUserProfile.isValid()) {
            //Login is needed.  Redirect the user to the login page.
            logMessage(debug, "No, you do not have a LtpaToken cookie. I'll redirect you to the login page now.");
            HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
            String redirectUrl = loginURL + "?page=" + getPageURL(http);
			logMessage(debug,redirectUrl);
            httpServletResponse.sendRedirect(redirectUrl);
        } else {

            //The user is authenticated.  Is access limited to a Domino Directory Group?
            if (!passGroupSecurity(dominoUserProfile)) {
                //The authenticated user is not a member of the security group, and my not continue.  Return status code (403) indicating the server understood the request but refused to fulfill it.
                logMessage(debug, "Access denied.  " + dominoUserProfile.getCommonName() + " is not a member of the Domino Security Group(s) defined in web.xml.");
                HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
                httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN, servletRequest.getServerName());
            } else {

                //The user is authenticated.  Store information in the user's session.
                if (storeInSession) {
                    //Get the username and password from the login form.             
                    session.setAttribute("DominoUserProfile", dominoUserProfile);                  
                   logMessage(debug, "I'm storing a DominoUserProfile in your session.");
                }

                //Continue loading the page requested by the user.
                logMessage(debug, "Welcome, " + dominoUserProfile.getCommonName());
                chain.doFilter(servletRequest, servletResponse);
            }
        }

    }


    /**
     * Determines if the user is a member of a Domino Directory group.
     * Groups are defined in web.xml.  This adds additional security to the web application.
     *
     * @param dominoUserProfile
     * @return true if the user is a member of the group, true if there is no group defined in web.xml, otherwise false.
     */
    private boolean passGroupSecurity(DominoUserProfile dominoUserProfile) {

        //Get the security group.  Optional.  This is defined in web.xml.
        String dominoSecurityGroupName = config.getInitParameter(DominoLoginFilterConstants.DOMINO_SECURITY_GROUP_NAME) == null ? "" : config.getInitParameter(DominoLoginFilterConstants.DOMINO_SECURITY_GROUP_NAME);

        //If there is no security group defined, then all authenticated users may continue.
        if (dominoSecurityGroupName.equals("")) {
            return true;
        }

        //Multi group names are delimited with the ; character.
        String[] g = dominoSecurityGroupName.split(";");

        //Is the authenticated user a member of the security group?
        for (int i = 0; i < g.length; i++) {
            if (dominoUserProfile.isMemberOfGroup(g[i].trim())) {
                return true;
            }
        }

        return false;
    }


    /**
     * @param http HttpServletRequest
     * @return Returns all parameters that appear in the URL.
     */
    private String getPageURL(HttpServletRequest http) {

        //What page was the user attempting to open?  This will be added to the RedirectTo data in the login form.
        StringBuffer queryString = http.getRequestURL();
        String str = queryString.toString();
        String str2 = http.getQueryString();
        if (str2 != null) {
            str += "?" + str2;
        }
        return str;
    }


    /**
     * Print a message to the log file.
     *
     * @param debug   Message is printed when this value is "1".
     * @param message The message to print.
     */
    private void logMessage(String debug, String message) {
        if (debug.equals("1")) {
            config.getServletContext().log(" " + config.getFilterName() + " - " + message);
        }
    }


    /**
     * Checks all requirements needed for this Filter to continue processing the request.
     * User's session must have an existing DominoUserProfile.
     * User's web browser must have an existing LtpaToken cookie.
     *
     * @param request
     * @param dominoUserProfile
     * @return true all requirements are found, otherwise false.
     */
    public boolean continueFilter(HttpServletRequest request, DominoUserProfile dominoUserProfile) {

        LtpaToken ltpaToken = new LtpaToken(request);

        if (dominoUserProfile != null) {
            if (dominoUserProfile.isValid()) {
                if (passGroupSecurity(dominoUserProfile)) {
                    if (ltpaToken.isValid()) {
                        return true;
                    }
                }
            }
        }

        return false;
    }


}
